package com.nasarius.bank.scorecard.web.controller.admin;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;

import javax.servlet.http.HttpServletRequest;

import org.apache.commons.collections.MapUtils;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.propertyeditors.CustomCollectionEditor;
import org.springframework.security.authentication.encoding.Md5PasswordEncoder;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.util.CollectionUtils;
import org.springframework.web.bind.ServletRequestDataBinder;
import org.springframework.web.bind.annotation.InitBinder;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;

import com.nasarius.bank.scorecard.dao.AuthorityDAO;
import com.nasarius.bank.scorecard.dao.BankDetailsDAO;
import com.nasarius.bank.scorecard.dao.UserBankDAO;
import com.nasarius.bank.scorecard.dao.UserDAO;
import com.nasarius.bank.scorecard.domain.Authority;
import com.nasarius.bank.scorecard.domain.BankDetails;
import com.nasarius.bank.scorecard.domain.UserBank;
import com.nasarius.bank.vo.AuthorityVO;
import com.nasarius.bank.vo.UserDetailsVO;

@Controller
public class UserDetailsController {
	protected final Log LOG = LogFactory.getLog(getClass());	
	@Autowired		
	private BankDetailsDAO bankDetailsDAO;		
	@Autowired		
	private UserDAO userDAO;
	@Autowired		
	private AuthorityDAO authorityDAO;
	@Autowired	
	private UserBankDAO userBankDAO;
	public void setUserBankDAO(UserBankDAO userBankDAO) {
		this.userBankDAO = userBankDAO;
	}
	public void setAuthorityDAO(AuthorityDAO authorityDAO) {
		this.authorityDAO = authorityDAO;
	}
	public void setUserDAO(UserDAO userDAO) {
		this.userDAO = userDAO;
	}
	@InitBinder
	protected void initBinder(ServletRequestDataBinder binder) {
			binder.registerCustomEditor(List.class,new CustomCollectionEditor(List.class));
	}	
	@ModelAttribute
	public UserDetailsVO newRequest(@RequestParam(required = false) String selectedUser, Model model,HttpServletRequest req) {
		UserDetailsVO userDetailsVO = new UserDetailsVO();
		List<Authority> allUserCredentials =null;		
		List<BankDetails> bankDetails = bankDetailsDAO.selectAllActiveBankDetails();	
		List<AuthorityVO> roleList = createRoleList();
		model.addAttribute("roleList", roleList);
		if(StringUtils.isBlank(selectedUser)){
			allUserCredentials = authorityDAO.selectAllUsers();
			createRoleList(allUserCredentials);	
			model.addAttribute("allUserCredentials",allUserCredentials);
			userDetailsVO.setBankDetailsList(bankDetails);
		}
		if(StringUtils.isNotBlank(selectedUser)){
			model.addAttribute("update","Y");
			userDetailsVO.setSelectedUser(userDAO.selectUserByPrimaryKey(selectedUser));
			userDetailsVO.getSelectedUser().setPassword(null);
			userDetailsVO.setSelectedUserAuthority(authorityDAO.selectUserAuthority(selectedUser));
			userDetailsVO.setSelectedBanks(userBankDAO.selectUserBank(selectedUser));
			userDetailsVO.setBankDetailsList(removeChosenBanks(bankDetails,userDetailsVO));
		}
		if(req.getParameter("updated")!=null && StringUtils.equals(req.getParameter("updated"),"Y")){
			model.addAttribute("updated","Y");
		}
		return userDetailsVO;
	}
    private List<BankDetails> removeChosenBanks(List<BankDetails> bankDetailsList,
			UserDetailsVO userDetailsVO) {
    	HashMap<String, UserBank> choosenBankMap = formChoosenBankMap(userDetailsVO.getSelectedBanks());
    	List<BankDetails> pendingBanks = new ArrayList<BankDetails>();
    	if(!CollectionUtils.isEmpty(bankDetailsList)){
    		for (int i=0; i<bankDetailsList.size(); i++){
    			BankDetails bankDetails = bankDetailsList.get(i);
    			String bankCode=bankDetails.getBankcode();
    			if(MapUtils.getString(choosenBankMap, bankCode) == null){
    					pendingBanks.add(bankDetails);
    			}
    		}
    	}else{
    		pendingBanks = bankDetailsList;
    	}
    	return pendingBanks;
	}
	private HashMap<String, UserBank> formChoosenBankMap(List<UserBank> selectedBanks) {
		HashMap<String, UserBank> choosenBankMap = new HashMap<String, UserBank>();
		if(!CollectionUtils.isEmpty(selectedBanks))
		for (int i=0;i<selectedBanks.size();i++){
			UserBank userBank = selectedBanks.get(i);
			choosenBankMap.put(userBank.getBankcode(), userBank);
		}
		return choosenBankMap;
		
	}
	private void createRoleList(List<Authority> allUserCredentials) {
		for (int i=0;i<allUserCredentials.size();i++){
			Authority authority = (Authority)allUserCredentials.get(i);
			if(authority.getAuthority().equalsIgnoreCase("ROLE_ADMIN")){
				authority.setAuthority("Administrator");
			}else if(authority.getAuthority().equalsIgnoreCase("ROLE_CBU")){
				authority.setAuthority("Central Bank User");
			}else if(authority.getAuthority().equalsIgnoreCase("ROLE_LBU")){
				authority.setAuthority("Local Bank User");
			}else if(authority.getAuthority().equalsIgnoreCase("ROLE_SURVEY")){
				authority.setAuthority("Surveyor");
			}
		}
	}
	@RequestMapping(value="/userdetails/deleteuser", method=RequestMethod.GET)
    public String deleteSurvey(@RequestParam(required = false) String selectedUser, Model model) {
    	authorityDAO.deleteAuthorityByPrimaryKey(selectedUser);
		userBankDAO.deleteUserBank(selectedUser);
    	userDAO.deleteUserByPrimaryKey(selectedUser);
		return "redirect:/userdetails/view.html"; 
    } 
	@RequestMapping(value="/userdetails/update", method=RequestMethod.POST)
    public String update(UserDetailsVO userDetailsVO, Model model) {
		String selectedUser = userDetailsVO.getSelectedUser().getUsername();
		String password = userDetailsVO.getSelectedUser().getPassword();
		userDetailsVO.getSelectedUser().setEnabled(Boolean.TRUE);
		userDetailsVO.getSelectedUserAuthority().setUsername(selectedUser);
		if(StringUtils.isNotBlank(password)){
			userDetailsVO.getSelectedUser().setPassword(encryptPassword(password));
		}
		if(userDAO.selectUserByPrimaryKey(selectedUser)==null){
			userDAO.insertUser(userDetailsVO.getSelectedUser());
			authorityDAO.insertAuthority(userDetailsVO.getSelectedUserAuthority());
		}else{
			if(StringUtils.isBlank(password)){
				userDetailsVO.getSelectedUser().setPassword(null);
			}
			userDAO.updateUserByPrimaryKeySelective(userDetailsVO.getSelectedUser());
			authorityDAO.updateAuthorityByUserName(userDetailsVO.getSelectedUserAuthority());
		}
		userBankDAO.deleteUserBank(selectedUser);
		List<String> selectedBankIDs = userDetailsVO.getSelectedBankIDs();
    	if(!CollectionUtils.isEmpty(selectedBankIDs)){
    		for(int i=0;i<selectedBankIDs.size();i++){
    			UserBank userBank = new UserBank();
    			userBank.setBankcode(selectedBankIDs.get(i));
    			userBank.setUsername(selectedUser);
    			userBankDAO.insertUserBank(userBank);
    		}
    	}
		model.addAttribute("updated","Y");
		return "redirect:/userdetails/edit.html?selectedUser="+selectedUser; 
    }	
	/**
     * <p>Person form request.</p>
     * 
     * <p>Expected HTTP GET and request '/userdetails/view'.</p>
     */
    @RequestMapping(value="/userdetails/view", method=RequestMethod.GET)
    public void form() {}	
    
    @RequestMapping(value="/userdetails/edit", method=RequestMethod.GET)
    public void edit() {}
    
	private static String encryptPassword(String password){
		Md5PasswordEncoder encoder = new Md5PasswordEncoder();
		return encoder.encodePassword(password, null);
	}
	public void setBankDetailsDAO(BankDetailsDAO bankDetailsDAO) {
		this.bankDetailsDAO = bankDetailsDAO;
	}	
	private List<AuthorityVO> createRoleList(){
		List<AuthorityVO> roleList = new ArrayList<AuthorityVO>();
		AuthorityVO authorityVO = new AuthorityVO();
		authorityVO.setRoleCode("ROLE_ADMIN");
		authorityVO.setRoleName("Administrator");
		roleList.add(authorityVO);
		AuthorityVO authorityVO1 = new AuthorityVO();
		authorityVO1.setRoleCode("ROLE_CBU");
		authorityVO1.setRoleName("Central Bank User");
		roleList.add(authorityVO1);
		AuthorityVO authorityVO2 = new AuthorityVO();
		authorityVO2.setRoleCode("ROLE_LBU");
		authorityVO2.setRoleName("Local Bank User");
		roleList.add(authorityVO2);		
		AuthorityVO authorityVO3 = new AuthorityVO();
		authorityVO3.setRoleCode("ROLE_SURVEY");
		authorityVO3.setRoleName("Surveyor");
		roleList.add(authorityVO3);			
		return roleList;
	}
}
